/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : app_freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "stdio.h"
#include "adc.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
_Bool mode=0;   //0:data    1:set
uint16_t VP1=240,VP2=240,vp1_temp=240,vp2_temp=240;
float volt_r37,volt_r38;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for LEDTask */
osThreadId_t LEDTaskHandle;
const osThreadAttr_t LEDTask_attributes = {
  .name = "LEDTask",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};
/* Definitions for KEYTask */
osThreadId_t KEYTaskHandle;
const osThreadAttr_t KEYTask_attributes = {
  .name = "KEYTask",
  .priority = (osPriority_t) osPriorityBelowNormal,
  .stack_size = 128 * 4
};
/* Definitions for ADCTask */
osThreadId_t ADCTaskHandle;
const osThreadAttr_t ADCTask_attributes = {
  .name = "ADCTask",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};
/* Definitions for LCDTask */
osThreadId_t LCDTaskHandle;
const osThreadAttr_t LCDTask_attributes = {
  .name = "LCDTask",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 256 * 4
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void LED_Task(void *argument);
void KEY_Task(void *argument);
void ADC_Task(void *argument);
void LCD_Task(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of LEDTask */
  LEDTaskHandle = osThreadNew(LED_Task, NULL, &LEDTask_attributes);

  /* creation of KEYTask */
  KEYTaskHandle = osThreadNew(KEY_Task, NULL, &KEYTask_attributes);

  /* creation of ADCTask */
  ADCTaskHandle = osThreadNew(ADC_Task, NULL, &ADCTask_attributes);

  /* creation of LCDTask */
  LCDTaskHandle = osThreadNew(LCD_Task, NULL, &LCDTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_LED_Task */
/**
  * @brief  Function implementing the LEDTask thread.
  * @param  argument: Not used
  * @retval None
  */
HexToBin led_ctrl;
/* USER CODE END Header_LED_Task */
void LED_Task(void *argument)
{
  /* USER CODE BEGIN LED_Task */
  /* Infinite loop */
  for(;;)
  {
      LED_Control(led_ctrl.hex);
      if(volt_r38>VP1)led_ctrl.b.b1 = 0;
      else led_ctrl.b.b1 = 1;
      if(volt_r37>VP2)led_ctrl.b.b2 = 0;
      else led_ctrl.b.b2 = 1;
    osDelay(20);
  }
  /* USER CODE END LED_Task */
}

/* USER CODE BEGIN Header_KEY_Task */
/**
* @brief Function implementing the KEYTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_KEY_Task */
void KEY_Task(void *argument)
{
  /* USER CODE BEGIN KEY_Task */
    uint8_t key_time=0,key_temp=0;
  /* Infinite loop */
  for(;;)
  {
      Key_Read();
      if(Trg)key_temp=Trg;
      if(Cont)key_time++;
      if(Trg==0 && Cont==0 && key_temp){
          if(key_time>=25){   //Long
              if(key_temp == 0x01)led_ctrl.b.b1=!led_ctrl.b.b1;
              if(key_temp == 0x02)led_ctrl.b.b2=!led_ctrl.b.b2;
              if(key_temp == 0x04)led_ctrl.b.b3=!led_ctrl.b.b3;
              if(key_temp == 0x08)led_ctrl.b.b4=!led_ctrl.b.b4;
          }else {     //short
              if(key_temp == 0x01){
                  mode = !mode;
                  if(mode==0){        //
                      VP1 = vp1_temp;
                      VP2 = vp2_temp;
                  } else{
                      vp1_temp=VP1;
                      vp2_temp=VP2;
                  }
              }
              else if(key_temp == 0x02 && mode==1) {
                  vp1_temp = vp1_temp + 30;
                  if (vp1_temp > 330)vp1_temp = 0;
              }
              else if(key_temp == 0x04 && mode==1) {
                  vp2_temp = vp2_temp + 30;
                  if (vp2_temp > 330)vp2_temp = 0;
              }
              else if(key_temp == 0x08)led_ctrl.b.b8=!led_ctrl.b.b8;
          }
          key_time=0;
          key_temp=0;
      }
    osDelay(20);
  }
  /* USER CODE END KEY_Task */
}

/* USER CODE BEGIN Header_ADC_Task */
/**
* @brief Function implementing the ADCTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_ADC_Task */
void ADC_Task(void *argument)
{
  /* USER CODE BEGIN ADC_Task */
  static float adc1_temp[3],adc2_temp[3];
  static uint8_t i=0,j=0;
  /* Infinite loop */
  for(;;)
  {
      HAL_ADC_Start(&hadc1);
      adc1_temp[i] = ((float )HAL_ADC_GetValue(&hadc1)*3.33f/4096.0f);
      HAL_ADC_Start(&hadc2);
      adc2_temp[j] = ((float )HAL_ADC_GetValue(&hadc2)*3.33f/4096.0f);
      if(++i==3)i=0;    //0 1 2 3 4
      if(++j==3)j=0;
      volt_r38 = (adc1_temp[0]+adc1_temp[1]+adc1_temp[2])/3.0f;
      volt_r37 = (adc2_temp[0]+adc2_temp[1]+adc2_temp[2])/3.0f;
    osDelay(20);
  }
  /* USER CODE END ADC_Task */
}

/* USER CODE BEGIN Header_LCD_Task */
/**
* @brief Function implementing the LCDTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_LCD_Task */
void LCD_Task(void *argument)
{
  /* USER CODE BEGIN LCD_Task */
    uint8_t buf[20];
  /* Infinite loop */
  for(;;)
  {
      if(mode==0){
          LCD_DisplayStringLine(Line3,(uint8_t *)"         DATA");
          sprintf((char*)buf,"     VR37:%.5fV",volt_r38);
          LCD_DisplayStringLine(Line5,buf);
          sprintf((char*)buf,"     VR38:%.5fV",volt_r37);
          LCD_DisplayStringLine(Line6,buf);
      }else{
          LCD_DisplayStringLine(Line3,(uint8_t *)"         PARA");
          sprintf((char*)buf,"     VP1:%4dV  ",vp1_temp);
          LCD_DisplayStringLine(Line5,buf);
          sprintf((char*)buf,"     VP2:%4dV  ",vp2_temp);
          LCD_DisplayStringLine(Line6,buf);
      }
    osDelay(50);
  }
  /* USER CODE END LCD_Task */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

